#ifndef __CONJUNTO_H__
#define __CONJUNTO_H__

#ifndef NULL
#define NULL 0
#endif

#include <iostream>
#include "defines.h"
#include "lista.h"

template<class T>
class Conjunto{
	public:
		Conjunto();
		Conjunto(const Conjunto&);
		~Conjunto();
		void agregar(const T elem);
		bool pertenece(const T elem) const;

		//esto es solo para testing! no se deben usar..
		bool operator==(const Conjunto&) const;
		bool operator=(const Conjunto&);
		void mostrarConjunto(ostream&) const;
		bool pertenecen(int elem) const; //para test catalogo
		int cardinal() const;
	private:
		Lista<T> conj;
};

template<typename T>
Conjunto<T>::Conjunto(const Conjunto& c){
    conj = c.conj;
}

template<typename T>
Conjunto<T>::Conjunto(){}

template<typename T>
Conjunto<T>::~Conjunto(){}

template<typename T>
void Conjunto<T>::agregar(const T elem){
	if (!conj.esta(elem)){
		conj.agregar(elem);
	}
}

template<typename T>
bool Conjunto<T>::pertenece(const T elem) const{
	return conj.esta(elem);
}

template<typename T>
void Conjunto<T>::mostrarConjunto(ostream& out) const{
	out << conj;
}

template<typename T>
bool Conjunto<T>::operator==(const Conjunto<T>& c) const{
    bool res = c.conj.longitud() == conj.longitud();
    if(res){
        typename Lista<T>::IterLista_const it1 = conj.crearIt_const();
        while(it1.tieneProximo()){
            if(!c.conj.esta(it1.actual())) res = false;
            it1.avanzar();
        }
    }
    return res;
}

template<typename T>
bool Conjunto<T>::operator=(const Conjunto<T>& c){
    conj = c.conj();
}

template<typename T>
ostream& operator<<(ostream& out, const Conjunto<T>& c) {
	c.mostrarConjunto(out);
	return out;
}

template<typename T>
bool Conjunto<T>::pertenecen(int elem) const{
	bool res = true;
	while(elem>=0 && res){
		if(!pertenece(elem)){
			res = false; 
		}
		elem--;
	}
	return res;
}

template<typename T>
int Conjunto<T>::cardinal() const{
	return conj.longitud();

}

#endif
